﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;

namespace ConsoleApplication1
{
    public class MainSearch
    {
        private MD5 _Md5Haser;
        private object sync = new object();
        public MD5 GetMD5Haser
        {
            get
            {
                if (_Md5Haser != null)
                {

                    return _Md5Haser;
                }
                else
                {
                    lock (sync)
                    {
                        if (_Md5Haser != null)
                        {
                            return _Md5Haser;
                        }
                        else
                        {
                            _Md5Haser = MD5.Create();
                            return _Md5Haser;
                        }
                    }
                }
            }

        }
        //public AddElementToListArgs 
        private List<UserFileInfo> _AllFiles = new List<UserFileInfo>();
        public int CountSerchedFiles
        {
            get { return _AllFiles.Count; }
        }
        /// <summary>
        /// считаем MD5?
        /// </summary>
        public bool CalcHash;
        /// <summary>
        /// Считаем ли мы вообще хэш как-нибудь или нет
        /// </summary>
        public bool DoHash;

        public List<UserFileInfo> Dublicates { private set; get; }
        object SyncO = new object();
        public void AddInfoToList(UserFileInfo uIn)
        {
            lock (SyncO)
            {
                _AllFiles.Add(uIn);
            }
        }
        public void StartSearch(string[] beginpath)
        {


            List<Task> waitTasks = new List<Task>();
            foreach (string p in beginpath)
            {
                DirectoryWorker dw = new DirectoryWorker(p, this);
                dw.DirectoryAccessEvent += new DirectoryWorker.DirectoryAccessHandler(dw_DirectoryAccessEvent);
                waitTasks.Add(Task.Factory.StartNew(dw.DoTask));

            }
            Task.WaitAll(waitTasks.ToArray());

        }

        public void GetDublicates()
        {
            List<UserFileInfo> result = new List<UserFileInfo>();
            List<int> temp = new List<int>();
            for (int i = 0; i < _AllFiles.Count; i++)
            {
                bool iisadd = false;
                UserFileInfo a1 = _AllFiles[i];
                for (int j = 0; j < _AllFiles.Count; j++)
                {
                    if (j != i && !temp.Contains(j))
                    {
                        UserFileInfo a2 = _AllFiles[j];
                        if (a2.Equals(a1))
                        {
                            temp.Add(j);
                            result.Add(a2);
                            if (!iisadd)
                            {
                                result.Add(a1);
                                iisadd = true;
                                temp.Add(i);
                            }
                        }
                    }
                }
            }
            Dublicates = result;

        }
        public void CalchHashParallel()
        {
            Parallel.ForEach(_AllFiles,
               a =>
               {

                   using (var fs = new FileStream(a.AllInfo.FullName, FileMode.Open, FileAccess.Read))
                   {
                       using (MD5 md5 = MD5.Create())
                       {
                           a.Md5FileHash = md5.ComputeHash(fs);
                       }


                   }


               });
        }



        public void dw_DirectoryAccessEvent(object o, DirecotyAccessDeniedEventArgs e)
        {
            Console.WriteLine("Нет доступа в : " + e.DirPath);
        }
    }
    public class AddElementToListArgs : EventArgs
    {
        public UserFileInfo AddedFile { private set; get; }
        public AddElementToListArgs(UserFileInfo fi)
        {
            this.AddedFile = fi;
        }
    }
}
